<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button>点我抽奖</button>
    <button>点我抽奖</button>
    <button>点我抽奖</button>
    <button>点我抽奖</button>
    <button>点我抽奖</button>
    <script>

        // var arr = ['再接再厉','谢谢回顾','宝马一辆','再来一次','特斯拉新能源']
        // var btns = document.querySelectorAll('button')
        // for(var i = 0;i<arr.length;i++){
        //     btns[i].index = i;
        //     console.log(btns[i].index)
        //     btns[i].onclick = function(){
        //         // innerHTML 操纵元素写法
        //         this.innerHTML = arr[this.index]
        //         console.log(this.innerHTML)
        //         console.log(arr[this.index])
        //     }
        // }        var null1 = null
        // var a1="10";
        // var a2=true;
        // var a3="hello";
        // console.log(Number(a1))         //返回10
        // console.log(Number(a2))         //返回1      
        // console.log(Number(a3))         //无法转换返回NAN
        // console.log(Number(undefined))  //无法转换返回NAN
        // console.log(Number("123r"))     //无法转换返回NAN
        // console.log(Number("00001"))    //返回1
        // console.log(Number("12元"))      //无法转换返回NAN
        // console.log(Number("12PX"))      //无法转换返回NAN
        // console.log(Number(null))        // 0
        // console.log(Number(''))          // 0       

        // 中括号操作符,
        // 当操作一个具体的属性值的时候可以使用点操作符
        // 当操作一个具体的属性或者一个变量的时候必须用中括号操作符

        // 普通函数-window
        // 事件函数-事件本身
        // 对象函数-对象本身
        // 定时器函数-window
        // 构造函数-实例对象
        // 原型对象-实例对象
        // 类-实例

        // 改变指向
        // call
        // 格式: 函数.call(新指向的位置,形参,形参)
        // apply
        // 格式:函数.apply(新指向的位置,[参数,参数])
        // bind
        // 格式:函数.bind(新指向的位置,参数,参数,参数)
        // 注意:bind不会调用函数会新建一个新函数,这个新函数无论怎么调用都不会再改变他的指向

        // call\apply\bind的区别
        // call和bind传参都是序列传参
        // apply是数组传参

        // call和apply改变指向都是调用函数
        // bind是新建一个新函数

        // this指向
        // 普通函数-window
        // 事件函数-触发事件函数的元素
        // 对象函数-对象本身
        // 定时器-window
        // 构造函数-实例对象
        // 原型对象-实例对象
        // 类-实例对象


        // js流程控制语句
        // 顺序语句  js按顺序逐个执行
        // 分支语句    if if-else else switch
        // 循环语句    for for -in  white do - white
        // 其他语句    continue    break

        // if语句
        // if 如果
        // else 否则
        // 格式:
        //     // if(条件) {
        //     //     条件成立执行的函数
        //     // }else if(条件) {
        //     //     条件成立执行的函数
        //     // }else {
        //     //     条件都不成立执行的函数
        //     // }

        // switch 
        //     格式
        //         switch(形参) {
        //             case 条件:条件成立执行的函数;brack
        //             dafualt:条件都不成立执行的函数;brack
        //         }

        // for循环
        //     格式
        //         for(初始化变量,条件,更新初始化的变量) {
        //             条件成立执行的函数
        //         }
        //         执行顺序
        //             先初始化变量
        //             判断条件是否成立
        //             条件成立就执行函数
        //             更新初始化的变量
        //             在判断条件是否成立,成立执行函数,更新初始化的变量,判断条件是否成立
        //             知道条件不成立
        //             退出循环
        // 双重for循环
        //     外面的循环执行一次里面的循环执行一遍
        // for - in
        //     格式:
        //         for(创建新变量 in 要遍历的数据) {
        //             如果遍历的是对象,这个新变量单独使用就是对象的属性名

        //             如果遍历的是数组,
        //             这个新变量单独使用就是数组的下标
        //             数组[新变量]这样输出的就是数组的元素

        //         }

        // white 
        //         格式: white(条件) {
        //                 循环体
        //                 更新循环体变量
        //         }
        // // do-white 
        // //         格式: do {
        // //             循环体
        // //             更新循环体变量
        // //         } white(条件)
        // // white和do-white的区别
        // //         white只有条件通过了才会执行
        // //         do-white不管条件成立不成立都会执行一次
        // // continue和break的区别
        // //         continue 是  跳过本次条件,不会终止程序
        // //         break是终止本次程序

        // // 自定义属性
        // //         标签不存在的
        // //         手写的f12看得到不生效
        // //         js的f12看不到生效
        // //         js的可以获取和设置
                

        // 转成number类型
        //     格式： number（要转换的数据）
        //         可以转化的数据，
        //         null，布尔类型，空字符串，纯数字的字符串类型
        //     其他的数据都是NAN
        // psrseInt转换 
        //     作用： 转换成 整数类型
        //     格式： parseInt（要转化的数据）
        //     从左到右依次转换 遇到转换不了的就停止并返回之前的数值，如果第一个就不成功返回nNA
        // parseInt 可以有两个参数
        //     格式：parseInt（数据，基数）
        //     基数就是要转换的进制 从2-36中选择，如果不写基数默认转换为 10进制
            
        // parseFloat
        //     作用：转换成浮点数
        //     格式parseFolat（要转化额数据）
        //     从左到右依次转换 遇到转换不了的就停止并返回之前的数值，如果第一个就不成功返回nNA

        // +号转换
        //     只能转换村字符串，其他的会转换成NAN

        // tpfixed 
        //     作用：保留几位小数
        //     格式： tofined(要保留纪委小数)
        //     注意：返回的值是字符串类型
        // 转换成字符串
        //     String和toString
        //     格式： string（要转换的值） toString（要转换的值）
        //     String 和 toString 的区别
        //     String可以转换任何数据类型，
        //     toString不可以抓换null和undefined
        // 转换Boolean类型
        //     格式： Boolean（要转换的值）

        //     双感叹号的作用:
        //         在js中一个感叹号的作用是取反并返回布尔值，再用感叹号取反就可以得到数据相对应的布尔值


        // string 类型
        //     又叫字符串类型
        //     特点： 字符串类型的数据都是可读不可修改的
        //         都有长度和小标，
        //         所有用引号引起来的都是字符串类型
        //         所有从页面中获取的数据都是字符串类型
        //     字符串类型是存储数据使用频率最高的类型，他的基本操作有
        //     。length获取字符串长度
        //     。charAt 根据下标获取字符串内容
        
        //     number类型
        //         number有整数、小数、进制、NAN
        
        // arrayshuzu
        // 也交数组类型
        //     特点：
        //         1. 数组就是存储多个数据的集合，所有数据都叫元素
        //         2. 每个数组都有length，代表数组的长度及
        //         3. 每个元素都有一个数字索引
        //         4. 数字索引是从0开始的，以此类推
        //         5. 数字索引的最大值永远比长度小1
        //         6. 数组的数据类型是对象类型，就是多了索引和长度的特殊对象
        //         7. 数组的数据的数据类型是不限的，可以是对象和函数

        // 算术运算符
        // 逻辑运算符
        // 三木表达式
        // 比较运算符
        // 赋值运算符

        // 算数    赋值    三元    比较运算符  逻辑运算符
        // 算数    赋值    逻辑运算符 三元 比较
        // 算数 +-*/%++--
        // 赋值 = +=-=*=/=
        // 逻辑 && 与 ||或 ！非
        // 比较><>=<===!====!===

        // 加号运算符遇上字符串会变成字符串拼接，全等于和非全等于会比较数据的内容和类型

        // 逻辑运算符
        //     && 条件必须都满足
        //     || 只需要满足其中一个条件即可
        //     返回值：如果有比较运算就返回布尔类型，如果没有就返回i自身
        //     ！非 取反

        // ++在前和++在后，
        //     ++在前是先运算再赋值
        //     ++在后是先赋值再运算


        // 函数：
        //         函数就是一个实现特定功能或者重复使用的代码段，不调用不会触发
        //         函数的声明
        //             普通函数： function 函数名（）{}
        //             表达式函数：var 变量名 = function（）{}
        //         普通函数和表达式函数的区别
        //             普通函数有函数名，表达式函数有变量名
        //             普通函数调用 函数名（） 表达式函数调用变量名（）
        //             普通函数可以在声明前调用，表达式不能
        //             普通函数不能自调用，表达式可以
        // 如果表达式和普通函数重名 表达式函数优先
        // 如果俩普通函数重名，后写覆盖前写的
        // 如果函数的参数和变量同名，参数优先

        // arguments 函数内置对象
        //     作用:该函数的所有实参都是存储到arguments中
        //     特点：有长度有下标
       
        // 函数的参数 函数的参数分为形参和实参
        //         一一对应不可多也不可少
        //         当有形参没有实参的时候  形参会被定义为undefined
        //         当有实参没有形参时，实参会被垃圾回收机制回收
        //         当形参多余实参是    多余的形参会被定义为undefined
        //         当实参多于形参时，实参会被垃圾回收机制回收
        // arguments
        // 作用：该函数的所有实参都存储在arguments中
        // 有长度有下标

        // return 返回值
        // 作用，吧函数内部的数据传递出去，方便外部调用
        // 当函数没有return时，返回的是undefined
        // return一次只能返回一个值
        // 如果想返回多个值，可以通过对象和数组来包裹
        // 函数遇到return会停止

        // 变量提升
        // 变量提升是浏览器在解析js代码时做的一个预解析的行为
        // 1. 寻找函数
        //     先寻找var定义的变量，找到后将他定义为undefined 类似：var a = undefined
        //     找完变量找函数，找到函数把整个函数提到最前面

        //     剩下的代码逐行排列并执行

        // 定时器及其应用场景
        //     延时定时器 setTimeout
        //     格式： setTimeout（函数，延迟的时间） 时间以毫秒计算
        //     特点：只执行一次，可以不用清除定时器
        //     应用场景：广告

        //     间隔定时器 setInterval
        //     格式： setInterval（函数，间隔多少秒）
        //     特点：间隔特定时间执行一次
        //     应用场景：轮播图和动画

        //     清除定时器
        //     如果我们达成了想要的效果就要清除定时器。
        //     每个定时器运行时都会产生一个定时器id（这个id从1开始）
        //     我们可以 定义一个变量 = 定时器 ，这个变量的值就是定时器id
        //     清除定时器格式：
        //         clearTimeout（定时器id） 作用：清除延时定时器
        //         clearInterval（定时器id）作用：清除间隔定时器

        //     操作元素的样式  
        //         style
        //         获取值  元素.style.属性名 {这里是只能获取行内样式}
        //         csstext:可以设置多个属性,会覆盖所有的行内样式,在没有设置相同属性名的情况下
        //         非行内样式不会被覆盖
        //         格式 元素.style.csstext = '属性名:属性值;属性名:属性值;'    

        //     数据类型
        //         基本数据类型
        //             number类型： 整数、小数、进制、NAN
        //             string类型（字符串类型）
        //             null（空值）
        //             undefined（未定义）
        //             Boolean类型（布尔值）
        //         复杂数据类型
        //             object（） 对象类型
        //             Array类型 数组类型
        //             function 函数 
        //     toFixed 数据保留几位小数
        //         格式： 数据.toFixed（保留几位小数）
        //         注意： 返回的数据都是字符串类型
                
        //     console.log 作用：输出内容到浏览器
        //         如果觉得每次都要写console。log太麻烦
        //         可以使用一下简写
        //             var a = console.log.bind(window)
        //     // 定时器this指向 
        //     // 普通函数-window
        //     // 对象函数-对象本身
        //     // 定时器-window
        //     // 构造函数-实例对象
        //     // 类-实例
        //     // 原型对象-实例对象

        //     运算符与隐式类型转换
        //         算术运算符
        //         赋值运算符
        //         逻辑运算符
        //         三木表达式
        //         比较运算符

        // 改变this指向的方法
        // 有三个
        //  call 、 apply 和bind
        //  call的格式
        //  call（新的this指向，参数，参数）
        //  apply（新的this指向，[参数，参数]
        //  bind（新的this指向，参数）
         
        //  call、apply、bind的异同
        //  call和apply改变this指向都是通过调用函数去修改的
        //  bind是创建一个新的函数不会调用函数，且这个函数无论怎么调用都不会再改变this指向

        //  call和bind传参都是序列传参
        //  apply是数组传参

        //  运算符与隐式类型转换
        //     算数
        //     赋值运算符
        //     三元表达式
        //     逻辑运算符
        //     比较运算符

        
        // 顺序语句:按顺序执行
        // 分支语句: if else if if switch
        // 循环语句: for for in   white  do-white
        // 其他 continue break
        
        // style
        // continue

        // js的特点
        //     js是基于对象和事件驱动的解释性脚本语言
        //     特点:
        //         基于对象:在js中万物皆对象,对象你可以看做是一个工具包或者是一个特殊功能的代码
        //         事件驱动:js可以直接响应用户的操作例如onmouseout鼠标滑上事件
        //         解释性:js不需要编译,在浏览器中可以直接执行
        //         跨平台性:js不需要其他环境,只要你的设备里有浏览器即可执行
        // ECMA规范
        //     在JavaScript火起来之后,多加IT公司发布了多个js版本,没有统一标准性,
        //     所以请来了ECMA(欧洲计算机制造商协会)来制定一套标准规范
        //     js第一套标准: ECMAscript1.1
        // ECMAscript和js的关系
        // ECMAscript是js的规范,而js是ECMAscript的实现
        // 需要学习的是
        //         DOM     bom ECMAscript规范
        // js的组成:
        //     DOM 文档对象
        //     bom 浏览器对象'
        //     ECMAscript js的规范

        // 获取 非行内 样式
        //     标准浏览器
        //     getComputedStyle(元素名).属性值
        //     IE浏览器 5 6 7 8不支持
        //     IE浏览器
        //     元素.current.属性名
        // 兼容写法
        //     // ele=元素名,arrt=属性值
        //     function getstyle(ele,arrt) {
        //         // 这里是为了判断浏览器有没有这个方法
        //         if(window.getComputedStyle) {
        //             return getComputedStyle(ele)[arrt]
        //         }else{
        //             return ele.current.arrt
        //         }
        //     }
        // js可以做的事:
        //     可以进行云计算
        //     可以使用浏览器方法
        //     可以在浏览器中使用js对象方法
        //     可以实现特殊效果
        //     可以进行表单验证

        // js的命名路程
        //     mocha-livescript-JavaScript

        
        // js的特点
        // js是基于对象和事件驱动的解释性脚本语言
        // 基于对象: 在js中万物皆对象 你可以看做是一个工具包或者是用来实现特定功能
        // 事件驱动: js可以直接响应用户的操作,例如 鼠标移入 onmouseout和鼠标移出onmouseEnd
        // 解释性: js无需编译即可直接在浏览器中执行
        // 跨平台型: js无需依赖额外环境,只要你的设备中有浏览器即可运行js

        // ECMA规范
        // 在js火了之后,多加IT公司发布了多个版本的js导致js没有统一标准
        // 所以请来了ECMA公司(欧洲计算机制造商协会)来指定一套统一的标准
        // 第一套js标准交 ECMAscript1.1

        // ECMAscript和js的关系
        // ECMAscript是js的规范
        // js是ECMAscript的实现

        // js能做的事情:
        //     进行云开发
        //     可以调用浏览器事件
        //     可以在浏览器中使用js对象方法
        //     可以进行表单验证
        //     可以实现特殊效果

        // 获取DOM的方式
        //     可以通过元素对的id获取
        //     特点：
        //         一次只能获取一个
        //         不可以动态获取
        //         只能通过dom获取
        //         当出现相同id时,css样式会全部实现,js效果只对第一个出该id的元素实现的
        //     通过标签名获取:
        //     特点:
        //         一次获取一组
        //         有长度有下标
        //         可以通过dom和父元素获取
        //         可以动态获取
        //     使用通过标签名获取的元素时要加下标
        //     通过class名获取
        //     一次获取一组
        //     有长度有下标
        //     可以通过

        // 字符串对象
        //     注意:字符串类型的数据都是可读不可修改的
        //     创建字符串
        //         字面量创建： var string1 = 'abc'
        //         调用函数创建: var string2 = String(123)
        //      字符串的属性:
        //         获取字符串长度可以用.length
        //         根据字符串下标获取数据:
        //         string1.charAr(index):根据下标获取字符串内容,找到返回对应的字符串,找不到返回空值
        //         string1[inex]:根据下标获取字符串内容,找到返回对应的字符串,找不到返回空值
        //         string1.charCodeAt(index):根据下标查找字符串并返回对应的ACSLL值,找不到返回NAN
        //     一般来说只有对象访问属性才可以使用.操作符,这里字符串访问属性和方法时会暂时被封装成一个对象,所以可以使用.操作符

        //     获取非行间样式
        //         分为标准浏览器和IE浏览器两种写法
        //         标准浏览器:
        //             格式:window.getComputedStyle(class名/id名).属性值

        //         IE浏览器:
        //             格式:class名/id名.currentStyle.属性

        //         兼容写法
        //             function  fn(ele,arrts) {
        //                 if(window.getgComputedStyle) {
        //                     return getComputedStyle(ele).arrts
        //                 }else {
        //                     return ele.currentStyle.arrts
        //                 }
        //             }

        // 字符串转大小写
        //     toLocaleLowerCase()     字母转成小写
        //     tolocaleUpperCase()     字母转成大写
            
        // 可选链:
        //     格式: 将. 换成 ?.
        //     作用: 判断?前面的 行为 是否定义,如果定义了就直接往下走,如果未定义就返回undefined停止执行(不会终止程序)
        //     js在执行时遇到 ?. 会隐式判断?. 前面是否为null或undefined,如果不是null和undefined就接着执行,如果是就返回undefined停止执行

        // Object.keys()
        //     格式: Object.keys(对象)
        //     作用: 返回对象所有可枚举的属性值的数组
        //     作用: 返回一个由对象自身key组成的数组  

        // Object.values()
        //     格式: Object.values(对象)
        //     作用: 返回一个有对象所有可枚举的属性值组成的数组
        //     返回的数组不能再被forEach,map等再操作
        
        // 字符串替换
        //     格式: rreplace('旧字符串','新字符串')
        //     作用: 把新字符串替换到旧字符串,只替换满足条件的第一个

        // ECMA规范
        //     在JS大火只有,多家IT公司发布了js,导致js规范不一致
        //     所以请来了ECMA(欧洲计算机制造商协会)来制定一套标准规范

        // js 命名变化
        //     mocha-mocha-livescript-JavaScript

        // 转换为本地事件
        //     tolocaleString: 转换出来的格式: 年/月/日  上/下午  时:分:秒
        //     tolocaleTImeString: 转换的格式 上/下午 时:分:秒
        //     tolocaleDateString: 转换的格式  年/月/日
        
        // 获取时间:
        //     年:getFullYear 月:getMonth 日:getDate 星期几:getDay 时:getHours
        //     分: getMinutes 秒:getSeconds 毫秒:getMilliSeconds
    
    // 时间戳：
    //     时间戳就是1970年1月1号0点0分0秒 至今的毫秒数
    //     两个时间之差也是一个时间戳
    //     获取时间戳的方法：
    //     date.getTime
    //     Date no  w()

    // hasOwnProperty
    //     格式:对象.hasOwnProperty(属性)
    //     作用:检测对象中是否有相应的属性
    //     返回值为Boolean 类型
    
    // 字符串转大小写
    //     tolocaleLowerCase 转小写
    //     toLocaleUpperCase 转大写
    
    // 字符串的查找
    //     格式:indexOf(要查找的字符串,下标)
    //     作用:查找对应的字符串第一次出现的地方
    //     特点:
    //         没有写下标的时候,默认从0开始查找
    //         找到就返回对应的下标,没有就返回-1

    //     格式: lastIndexOf(要查找的字符串,下标)
    //     作用: 查找字符串最后一次出现的位置
    //     注意: 
    //         当下标没有写的时候,默认从字符串.length开始查找
    //         从后往前查找,找到了返回对应的下标,没找到就返回-1

    // 字符串对象
    //     注意:字符串类型的数据都是可读取不可修改的
    //     创建方式:
    //         字面量创建: var a = 'abc'   String类型
    //         调用函数创建: var b = string(123)

    //     字符串的长度可以使用字符串.length去获取
    //     字符串通过下标获取数据的方式
    //         字符串[indedx]:根据下标获取相应的数据,没有就返回 空
    //         字符串.charAt(index):根据下标获取相应的数据,没有就返回空
    //         字符串.charCodeAt(indx):根据下标获取相应的数据的ACSLL值,没有就返回NAN

    //     字符串的截取
    //         数字对象:
    //         内置对象有 Date 时间对象 Math 数字对象 String 字符串对象
            
    //         toPrecision
    //         格式: number.toPrecision(要保留几位数)
    //         特点:
    //             会自动四舍五入
    //             将number格式转换为指定格式,并返回转换后的字符串的值
    //         注意: 要保留的几位数的值不能大于100大于100会报错

    //         数字对象
    //         random:随机数
    //         floor:向下取整
    //         ceil:向上取整
    //         round:四舍五入
    //         abs:绝对值
    //         sqrt:去根号
    //         pow:取几次幂
    //         max:最大值
    //         min:最小值

    //         toPrecision
    //         格式:number.toPrecision(要保留几位数)
    //         特点:
    //             将number转换为指定保留几位数,返回转换后的字符串值
    //             自动四舍五入
    //         注意: 要保留几位数的值不能大于100,大于100会报错

    //         时间对象:String类型
    //             获取年是 getFullYear
    //             月是 getMonth
    //             日是 getDate
    //             星期几是 getDay
    //             时是:getHours
    //             分是: getMinute
    //             秒:getSeconds
    //             毫秒是:getMilliSecond

    //             时间戳
    //             时间戳就是1970年1月1日 0点0分0秒至今的毫秒数
    //             两个时间的差也是时间戳
    //             获取时间戳的方式
    //             date.getTime
    //             now Date()

    //     截取字符串
    //         格式: substr(开始下标,'截取的长度')
    //         特点:
    //             如果没有截取的长度就从开始下标开始一直截取到没有
    //             包含开始下标和结束下标
    //             如果没有参数就截取所有
    //             如果截取的长度为负数就倒过来截取 
                
    //         格式:subString(开始下标,结束下标)
    //         特点:
    //             当结束下标为负数时,默认调换位置
    //             如果开始下标为负数,默认为0
    //             返回值为一个伪数组
    //             有长度有下标

    //         格式: slice(开始下标,结束下标)
    //         特点:
    //             当结束下标/开始下标为0时, 下标=字符串.length+负数
    //             有长度有下标
    //             截取长度包含开始下标不包含结束的下标


    //     截取字符串
    //         格式:字符串.substr(开始下标,截取长度)
    //         特点: 
    //             截取的长度包含开始下标和截取下标
    //             当截取的长度为0时,倒过来截取

    //         格式:字符串.subString(开始下标,结束下标)
    //         特点: 
    //             截取的长度包含开始下标不包含结束下标
    //             当结束下标为负数时,默认为0并移到前面去
    //             当开始下标为0时,默认为0
                
    //         格式:字符串.slice(开始下标,结束下标)
    //         特点: 
    //             截取的长度包含开始下标,不包含你结束下标
    //             当开始下标或者结束下标为负数时,下标=字符串的长度-负数
    //             如果开始下标大于结束下标,会返回'

    //         slice,substr,substring的q区别
    //         slice和subString截取的长度都是包含开始下标不包含结束下标
    //         substr包含结束下标和开始下标

    //         slice不会改变位置
    //         subString在结束下标为负数时会改变参数的位置

    //     字符串的截取
    //         格式:字符串.substr(开始下标,截取的长度)
    //         特点:
    //             截取的长度包含开始下标和截取下标
    //             当截取的长度为负数时,倒过来截取
            
    //         格式:字符串.substring(开始下标,结束下标)
    //         特点:
    //             截取的长度包含开始下标不包含结束下标
    //             当开始下标为负数时,默认为0
    //             但结束下标为0时,默认为0自动更换位置
                
    //         格式:字符串.slice(开始下标,结束下标)
    //         特点:
    //             截取的长度包含开始下标不包含结束下标
    //             当下标为负数时,下标=字符串的长度+负数

    //     可选链:
    //         格式:将.替换成?.
    //         特点:
    //             js在执行时遇到?.也就是可选链的时候,会隐式判断可选链前面的行为是否为null或undefined
    //             如果是就返回undefined停止执行,如果不是就接续执行
    //     hasOwnProperty
    //         格式: Object.hasOwnProperty(键)
    //         作用:查找对象中是否有对应的键,如果有就返回true没有就返回falue


    //     Object.assign
    //         格式: Object.assign(目标对象,源对象,源对象)
    //         作用: 将一个或多个源对象中可枚举的属性值给到目标对象
    //         注意: 当目标对象中和后面的源对象有相同的属性值时,源对象的值会覆盖目标对象的属性值

    //     Object.values
    //         作用:返回一个由自身可枚举值的数组
    //         格式: Object.values(对象)

    //     Object.keys[]
    //         作用:返回一个由自身key组成的数组
    //         格式: Object.keys[对象]

    // 数组转字符串
    //         格式: arr.join('分隔字符')
    //         特点: 将数组分个字符分隔成字符串

    //     截取数组:
    //         格式: arr.slice(开始下标,结束下标)
    //         特点: 从开始下标截取到结束下标,返回数组2
    //         截取数组并返回新的数组
    //     数组的增加与删除
    //         push() 从尾部开始增加
    //         pop() 从尾部开始删除
    //         shift() 从头部开始增加
    //         unshift() 从头部开始删除

    //     修改数组
    //         格式:   arr.splice(开始下标,要删除几位数,添加)
    //         作用:   修改数组    返回删除的值
    //         一个下标,从开始删除到末尾
    //         两个参数,从开始的下标删除定义的几位数
    //         三个下标,在下标开始的地方删除2或者添加几位
    //         控制台打印的是最后一条数据的结果

    //     数组的排序-sort
    //         格式: arr.sort()
    //         特点: 将数组按照顺序排列好
    //         没有参数时默认以字符串编码排序
    //         假设接收参数a 和 b 时,
    //         返回a - b 就是从小到大,返回b-a就是从大到小排序
        
    //     数组的迭代
    //         在js中迭代通俗的讲就是遍历,类似于for循环,有五种常用的迭代方式
    //         特点:   接收一个函数作为参数,这个函数有三个参数,
    //         values是指每一个项,index是下标,array是对象本身
        
    //     every
    //     格式: arr.every()
    //     特点: 每一项都会执行定义的函数,有一项为假就输出假,每一项都不为为假就输出真

    //     some
    //     格式: arr.some()
    //     特点: 每一项都会执行特定的函数,有一项为真就输出真,每一项都为假就输出假

    //     filter
    //     格式: arr.filter()
    //     特点: 每一项都执行定义的函数,返回一个由满足条件项组成的数组

    //     Map
    //     格式: arr.map()
    //     特点: 每一项都会执行定义的函数,返回一个由所有项执行的结果组成的数组

    //     forEach
    //     格式: arr.forEach() 
    //     和for循环一样,只是一个循环而已,没有返回值

    //     every some filter map forEach\

    //     every.some.filter必须有返回值
    //     查找数组中是否有对应的值
    //     arr.includes(值,开始下标)
        
    //     值是必须的,
    //     开始下标可有可无,作用是从开始下标查找

    
    //     flat
    //     作用：将一个数组深度遍历,并返回一个由所有元素和子数组的元素组成的数组
    //     当没有指定的参数是,默认为1
    //     arr.flat()会去除空值


    //     分隔数组
    //     格式: arr.join(分隔的字符)
    //     作用: 根据字符把字符串分割成字符串

    // 滚轮事件
    //     鼠标中间滚动的时候js也能监听到
    //     标准和IE浏览器的滚轮事件与火狐的不一致

    //     IE和标准浏览器
    //     格式: 元素.onmousewheel=function(){c('标准滚动')}

    //     火狐浏览器
    //     格式: 元素.addEventListener('DOMMouseWheel',function(){c('火狐滚动')})

    //     判断滚轮的方向
    //     IE和标准浏览器
    //     关键字: ev.wheelDelte

    //     搜狗: ev.wheelDelta 值为 -120 时往下 值为 120 时往上
    //     谷歌和edge:ev.wheelDelta 值为 -150时往下 值为150时往上滑
        
    //     火狐判断:
    //     ev.detai值为 -3 时往下 值为 3 时往上

    clientHeight 获取元素高度，高和上下padding，不包括border
    clientwidth 获取元素宽度，宽和左右padding，不包含border
    clientLeft 获取元素的左边框大小
    clientTop 获取元素的上边框大小
    document。body。clientHeigth 获取body的高度
    doucment。body。clientwidth 获取body的宽度
    document.documentElement.clientHeight 获取HTML 可视化的高度
    doucment.documentElement.clientwidth 获取HTMl可是的宽度

    offsetWidth 获取元素的宽度 padding+宽+border
    offsetHeight 获取元素的宽度 padding+高+border

    offsetLeft 获取元素距离有定位的父元素的左边框的距离
    offsetTop 获取元素距离有定位的父元素的上边框的距离

    onscroll
    元素滚动
    window.onscroll   window滚动事件
    document.body.onscroll  body滚动事件
    document.onscroll HTML滚动事件

    doucment.documentElement.scrollTop  获取页面被卷曲的高度
    document.documentElement.scrollLeft 获取页面被卷起的宽度

    页面懒加载
    作用: 根据需求加载数据,减少数据请求,提高页面性能
    原理: 遍历加载数据的元素,判断是否需要加载数据
          页面距离顶部的高度<=页面的可视高度-页面被卷起的宽度
          oli[i].offsetTop <= document.documentElement.clientHeight-document.documentElement.scrollTop

          onclick 点击事件
          onmouseover 鼠标滑上事件
          onmouseleave 鼠标滑下事件
          onmouseenter 鼠标移入事件
          onmouseout 鼠标移出事件
          ondblclick 鼠标双击事件
          onmousedown 鼠标按下事件
          onmousemove 鼠标移动事件
          
          onresize 当浏览器尺寸发生改变时自动触发
        
          常用键盘事件
          onkeydown 键盘按下    所有按键都能触发
          onkeypress 键盘弹起事件 上下左右这些不能触发onkeypress 
          注意: 
            每个按键都有对应的编码值
            这个事件只能添加给document

        事件对象就是 存储一些鼠标信息和事件相关的内置对象event
        兼容写法 var ev = window.event || evn
        evn是通过形参传递的,内置在实参中的,自定义命名

        阻止事件默认行为
        事件默认行为就是标签自带的行为,比如a标签的点击跳转,如果不想要可以手动阻止,你通的
        绑定方法不同组织写法也不同
        普通事件绑定 -- retrun false
        标准浏览器 -- ev.preventDefault()方法
        IE ev.retrunValues = false


        阻止事件冒泡
        阻止事件冒泡就是当子元素接收事件后,阻止父元素在触发事件 
        e.stopPropagation
        iE cancelBubble = true
        标准浏览器 ev.stopPropagation()方法
        IE ev.canselBubble = true 

        闭包就是函数嵌套函数的
            内部函数可以访问外部函数的变量和参数度
            内部函数的参数度和变量会永驻内存
        
</script>    
</body>
</html>